package cn.com.oyat.idea.service;

import cn.com.oyat.idea.model.DlnaDevice;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.springframework.stereotype.Service;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class DlnaService {

    private static final String UPNP_MULTICAST_ADDRESS = "239.255.255.250";
    private static final int UPNP_MULTICAST_PORT = 1900;
    private static final String UPNP_SEARCH_MESSAGE =
            "M-SEARCH * HTTP/1.1\r\n" +
                    "HOST: 239.255.255.250:1900\r\n" +
                    "MAN: \"ssdp:discover\"\r\n" +
                    "MX: 3\r\n" + // 最大等待时间
                    "ST: urn:schemas-upnp-org:device:MediaRenderer:1\r\n" + // 只搜索媒体渲染器
                    "\r\n";

    /**
     * 发现局域网内的DLNA渲染器（机顶盒）
     */
    public List<DlnaDevice> discoverDevices() throws IOException {
        List<DlnaDevice> devices = new ArrayList<>();
        byte[] sendData = UPNP_SEARCH_MESSAGE.getBytes();

        try (DatagramSocket socket = new DatagramSocket()) {
            socket.setSoTimeout(5000); // 设置超时5秒
            InetAddress group = InetAddress.getByName(UPNP_MULTICAST_ADDRESS);
            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, group, UPNP_MULTICAST_PORT);
            socket.send(sendPacket);

            long startTime = System.currentTimeMillis();
            // 持续监听响应，直到超时
            while (System.currentTimeMillis() - startTime < 5000) {
                try {
                    byte[] buf = new byte[1024];
                    DatagramPacket receivePacket = new DatagramPacket(buf, buf.length);
                    socket.receive(receivePacket);
                    String response = new String(receivePacket.getData(), 0, receivePacket.getLength());
                    DlnaDevice device = parseSsdpResponse(response, receivePacket.getAddress().getHostAddress());
                    if (device != null) {
                        devices.add(device);
                    }
                } catch (java.net.SocketTimeoutException e) {
                    break; // 超时退出
                }
            }
        }
        return devices;
    }

    /**
     * 解析SSDP响应，提取设备信息
     */
    private DlnaDevice parseSsdpResponse(String response, String ip) {
        // 使用正则表达式从响应头中提取LOCATION (设备描述文档的URL)
        Pattern locationPattern = Pattern.compile("LOCATION:\\s*(.*)\\r?\\n", Pattern.CASE_INSENSITIVE);
        Pattern usnPattern = Pattern.compile("USN:\\s*(.*)\\r?\\n", Pattern.CASE_INSENSITIVE);
        Pattern serverPattern = Pattern.compile("SERVER:\\s*(.*)\\r?\\n", Pattern.CASE_INSENSITIVE);

        Matcher locationMatcher = locationPattern.matcher(response);
        if (locationMatcher.find()) {
            String locationUrl = locationMatcher.group(1).trim();
            DlnaDevice device = new DlnaDevice();
            device.setLocation(locationUrl);
            device.setIp(ip);

            // 可选：从LOCATION URL获取更详细的设备信息（如友好名称）
            try {
                fetchDeviceDetails(device);
            } catch (Exception e) {
                System.err.println("Failed to fetch details for device at " + locationUrl);
            }
            return device;
        }
        return null;
    }

    /**
     * 获取设备的详细描述（名称、服务等）
     */
    private void fetchDeviceDetails(DlnaDevice device) throws Exception {
        String location = device.getLocation();
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet request = new HttpGet(location);
            try (CloseableHttpResponse response = httpClient.execute(request)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    String result = EntityUtils.toString(entity);
                    // 简单解析XML，获取友好名称
                    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = factory.newDocumentBuilder();
                    Document doc = builder.parse(new ByteArrayInputStream(result.getBytes()));

                    NodeList friendlyNameList = doc.getElementsByTagName("friendlyName");
                    if (friendlyNameList.getLength() > 0) {
                        device.setFriendlyName(friendlyNameList.item(0).getTextContent());
                    }

                    // 更完善的实现应该在这里解析<serviceList>，找到AVTransport服务的controlURL
                    // 这里为了简化，我们稍后在推送时再动态获取
                    EntityUtils.consume(entity);
                }
            }
        }
    }
}